package com.zb.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zb.constant.NetworkConstant;
import com.zb.entity.*;
import com.zb.exception.SMSException;
import com.zb.extend.NetworkEmpRelationExtend;
import com.zb.extend.NetworkExtend;
import com.zb.mapper.ZjNetworkMapper;
import com.zb.mobile.NetworkMobileInfoVo;
import com.zb.result.PageUtil;
import com.zb.service.*;
import com.zb.util.MobileNetworkSmsUtil;
import com.zb.utils.RandomUtil;
import com.zb.view.ViewNetworkEmpDetail;
import com.zb.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * <p>
 * 网点表 服务实现类
 * </p>
 *
 * @author WEN
 * @since 2023-10-18
 */
@Slf4j
@Service
public class ZjNetworkServiceImpl extends ServiceImpl<ZjNetworkMapper, ZjNetwork> implements ZjNetworkService {
    @Resource
    private ZjNetworkMapper networkMapper;
    @Resource
    private ZjAccountService accountService;
    @Resource
    private ZjNetworkEmpService networkEmpService;
    @Resource
    private ZjNetworkEmpRelationService networkEmpRelationService;
    @Resource
    private ZjNetworkPathService networkPathService;
    @Resource
    private ZjNetworkStrategyService networkStrategyService;
    @Resource
    private ZjNetworkWithdrawWithFeeEmpRootService networkWithdrawWithFeeEmpRootService;
    @Resource
    private ZjNetworkFieldValService networkFieldValService;
    @Resource
    private ZjNetworkFieldValOptionService networkFieldValOptionService;
    @Resource
    private ZjNetworkModuleSettlementService networkModuleSettlementService;
    @Resource
    private ZjNetworkServiceAreaService networkServiceAreaService;
    @Resource
    private ViewNetworkEmpDetailService viewNetworkEmpDetailService;
    @Resource
    private ZjNetworkTypeService networkTypeService;
    @Resource
    private ZjNetworkEmpFieldValService networkEmpFieldValService;
    @Resource
    private ZjNetworkEmpFieldValOptionService networkEmpFieldValOptionService;
    @Resource
    private ZjNetworkEmpAuthenFieldValService networkEmpAuthenFieldValService;

    // 新增或修改服务商
    @Override
    @Transactional
    public void save(AccounLoginInfo logintInfo, NetworkVo networkVo) {
        Assert.isTrue(null == networkMapper.existByName(logintInfo.getCustAccId(), networkVo.getId(), networkVo.getName()), "服务商名称已重复！");
        if (StringUtils.isNotBlank(networkVo.getCode())) {
            Assert.isTrue(null == networkMapper.existByCode(logintInfo.getCustAccId(), networkVo.getId(), networkVo.getCode()), "服务商编码已重复！");
        }
        if (networkVo.getCategory() == 3) {
            Assert.isTrue(StringUtils.isNotBlank(networkVo.getPath()), "接口路径不能为空");
            Assert.isTrue(StringUtils.isNotBlank(networkVo.getPublicKey()), "数据加密公钥不能为空");
        }

        ZjNetwork network = new ZjNetwork();
        BeanUtil.copyProperties(networkVo, network);
        network.setType(0);
        network.setDisabled(networkVo.getStatus());
        network.setUpdateEmpId(logintInfo.getId());
        network.setUpdateEmp(logintInfo.getName());
        network.setTeamType(null == network.getTeamType()? 2 : network.getTeamType());
        if (null != network.getId()) {
            this.updateById(network);
        } else {
            network.setId(IdWorker.getId());
            network.setCustAccId(logintInfo.getCustAccId());
            network.setNetworkTypeId(null == networkVo.getNetworkTypeId()? 0L : networkVo.getNetworkTypeId());
            network.setCode(RandomUtil.random10());
            network.setTeamAuthenStatus(NetworkConstant.NETWORK_TEAM_OR_ALONE_AUTHEN_STATUS_1);
            network.setAloneAuthenStatus(NetworkConstant.NETWORK_TEAM_OR_ALONE_AUTHEN_STATUS_1);
            network.setTown(null == network.getTown()? "" : network.getTown());
            network.setCreateEmpId(logintInfo.getId());
            network.setCreateEmp(logintInfo.getName());
            this.save(network);
        }
        networkStrategyService.save(logintInfo.getCustAccId(), network.getId(), networkVo.getStrategy());
        Long accountId = accountService.getOrSave(networkVo.getAccountId(), networkVo.getPhone(), null, networkVo.getAccountName(), "");
        Long networkEmpId = networkEmpService.saveNetworkManager(accountId);
        networkEmpRelationService.saveNetworkManager(logintInfo.getCustAccId(), network.getId(), networkEmpId);
        networkPathService.save(logintInfo.getCustAccId(), network.getId(), networkVo.getPath(), networkVo.getPublicKey());
        networkFieldValService.save(logintInfo.getCustAccId(), network.getId(), networkVo.getFieldVals());
        networkModuleSettlementService.save(logintInfo.getCustAccId(), network.getId(), networkVo.getModuleSettlements(), networkVo.getDelModuleSettlementIds());
        if (null == networkVo.getServiceAreas() || CollectionUtil.isEmpty(networkVo.getServiceAreas())) {
            List<NetworkServiceAreaVo> serviceAreas = new ArrayList<>();
            serviceAreas.add(new NetworkServiceAreaVo(networkVo.getProvince(), networkVo.getCity(), networkVo.getArea(), ""));
            networkVo.setServiceAreas(serviceAreas);
        }
        networkServiceAreaService.save(logintInfo.getCustAccId(), network.getId(), networkVo.getServiceAreas());
    }

    // 获取服务商列表
    @Override
    public List<NetworkListVo> getList(Long custAccId, NetworkSelectVo networkSelectVo) {
        List<NetworkExtend> networkList = getListExtend(custAccId, networkSelectVo);

        List<Long> networkTypeIdsd = networkList.stream().map(ZjNetwork::getNetworkTypeId).distinct().toList();
        List<Long> networkIds = networkList.stream().map(ZjNetwork::getId).toList();
        List<ZjNetworkType> typeList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(networkTypeIdsd)) {
            typeList.addAll(networkTypeService.listByIds(networkTypeIdsd));
        }
        List<ZjNetworkStrategy> strategyList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(networkIds)) {
            strategyList.addAll(networkStrategyService.listByIds(networkIds));
        }
        List<NetworkListVo> voList = networkList.stream().map(network -> {
            NetworkListVo vo = new NetworkListVo();
            BeanUtil.copyProperties(network, vo);
            vo.setStatus(network.getDisabled());
            vo.setAutoSureReceiveOrder(strategyList.stream().filter(f -> Objects.equals(f.getId(), network.getId())).map(ZjNetworkStrategy::getAutoSureReceiveOrder).findFirst().orElse(false));
            vo.setCreateTime(network.getGmtCreate());
            vo.setUpdateTime(network.getGmtUpdate());
            vo.setNetworkType(typeList.stream().filter(f -> Objects.equals(f.getId(), network.getNetworkTypeId())).map(ZjNetworkType::getName).findFirst().orElse(""));
            return vo;
        }).toList();
        return voList;
    }

    // 获取服务商列表总记录数
    @Override
    public long getListCount(Long custAccId,  NetworkSelectVo networkSelectVo) {
        return networkMapper.getListCount(custAccId, networkSelectVo);
    }

    // 获取服务商列表继承类信息
    @Override
    public List<NetworkExtend> getListExtend(Long custAccId, NetworkSelectVo networkSelectVo) {
        return networkMapper.getList(custAccId, networkSelectVo);
    }

    // 获取服务商下拉数据
    @Override
    public Map<String, Object> getNetworkPageSelect(Long custAccId, Integer type, SelectVo selectVo) {
        PageUtil.setSelectPageLimit(selectVo);
        QueryWrapper<ZjNetwork> wrapper = new QueryWrapper<>();
        wrapper.select("id", "name", "category", "team_type");
        wrapper.eq("cust_acc_id", custAccId)
                .eq("is_disabled", false);
        if (null != type) {
            wrapper.eq("type", type);
        }
        if (StringUtils.isNotBlank(selectVo.getName())) {
            wrapper.like("name", selectVo.getName());
        }
        Page<ZjNetwork> page = this.page(new Page<>(selectVo.getPage(), selectVo.getLimit()), wrapper);
        List<SelectNetworkVo> voList = page.getRecords().stream().map(network -> {
            return new SelectNetworkVo(network.getId(), "【" +
                    (NetworkConstant.CATEGORY_1 == network.getCategory() ? NetworkConstant.CATEGORY_STR_1 :  NetworkConstant.CATEGORY_STR_2) + "】" + network.getName(),
                    network.getTeamType(),
                    network.getCategory());
        }).toList();
        return PageUtil.pageList(page.getCurrent(), page.getSize(), page.getTotal(), voList);
    }

    // 根据服务商分类或区域查询对应的服务商
    @Override
    public Map<String, Object> getNetworkSelect(Long custAccId, NetworkSelectSearchVo searchVo) {
        PageUtil.setSelectPageLimit(searchVo);
        if (searchVo.getType() == 2 || searchVo.getType() == 3) {
            Assert.notNull(searchVo.getAreaType(), "当查询条件为：‘服务区域’或‘客户地址’ 时，地址区域类型不能为空");
        }
        long count = networkMapper.getNetworkSelectCount(custAccId, searchVo);
        if (count <= 0) {
            return PageUtil.pageList(searchVo.getPage(), searchVo.getLimit(), count, new ArrayList<>());
        }
        List<ZjNetwork> networkList = networkMapper.getNetworkSelect(custAccId, searchVo);
        return PageUtil.pageList(searchVo.getPage(), searchVo.getLimit(), count, networkList.stream().map(network -> {
            return new SelectNetworkVo(network.getId(), "【" +
                    (NetworkConstant.CATEGORY_1 == network.getCategory() ? NetworkConstant.CATEGORY_STR_1 :  NetworkConstant.CATEGORY_STR_2) + "】" + network.getName(),
                    network.getTeamType(),
                    network.getCategory());
        }).toList());
    }


    // 根据服务商ID获取修改服务商前的信息
    @Override
    public NetworkVo getBeforeNetworkEditSelect(Long id) {
        ZjNetwork network = this.getById(id);
        Assert.isTrue(null != network, "服务商ID参数["+ id +"]的数据不存在");

        NetworkVo vo = new NetworkVo();
        BeanUtil.copyProperties(network, vo);
        vo.setStatus(network.getDisabled());

        ViewNetworkEmpDetail empDetailView = viewNetworkEmpDetailService.getManagerByNetworkId(id);
        vo.setAccountId(empDetailView.getAccountId());
        vo.setAccountName(empDetailView.getAccountName());
        vo.setPhone(empDetailView.getAccountPhone());

        ZjNetworkStrategy strategy = networkStrategyService.getById(id);
        NetworkStrategyVo strategyVo = new NetworkStrategyVo(strategy);
        // 查询提现与查询费用人员权限
        List<ZjNetworkWithdrawWithFeeEmpRoot> withdrawWithFeeEmpRootList = networkWithdrawWithFeeEmpRootService.getByNetworkId(id);
        strategyVo.setWithdrawEmpRootVos(withdrawWithFeeEmpRootList.stream().filter(f -> f.getType() == 1).map(ZjNetworkWithdrawWithFeeEmpRoot::getNetworkEmpId).toList());
        strategyVo.setSelectFeeEmpRootVos(withdrawWithFeeEmpRootList.stream().filter(f -> f.getType() == 2).map(ZjNetworkWithdrawWithFeeEmpRoot::getNetworkEmpId).toList());
        vo.setStrategy(strategyVo);
        if (network.getCategory() == 3) {
            ZjNetworkPath path = networkPathService.getById(id);
            vo.setPath(path.getPath());
            vo.setPublicKey(path.getPublicKey());
        }

        List<ZjNetworkFieldVal> fieldVals = networkFieldValService.getByNetworkId(id);
        List<ZjNetworkFieldValOption> valOptionList = networkFieldValOptionService.getByNetworkId(id);
        vo.setFieldVals(fieldVals.stream().map(fieldVal -> {
            NetworkFieldValVo fieldVo = new NetworkFieldValVo();
            BeanUtil.copyProperties(fieldVal, fieldVo);
            fieldVo.setFieldId(fieldVal.getNetworkFieldId());
            fieldVo.setOptVos(valOptionList.stream().filter(f -> Objects.equals(f.getNetworkFieldValId(), fieldVal.getId())).map(opt -> {
                return new FieldValOptionVo(opt.getId(), opt.getOptValue());
            }).toList());
            return fieldVo;
        }).toList());

        List<ZjNetworkModuleSettlement> networkModuleSettlements = networkModuleSettlementService.getByNetworkId(id);
        vo.setModuleSettlements(networkModuleSettlements.stream().map(networkModule -> {
            NetworkModuleSettlementVo networkModuleSettlementVo = new NetworkModuleSettlementVo();
            BeanUtil.copyProperties(networkModule, networkModuleSettlementVo);
            return networkModuleSettlementVo;
        }).toList());

        List<ZjNetworkServiceArea> serviceAreas = networkServiceAreaService.getByNetworkId(id);
        vo.setServiceAreas(serviceAreas.stream().map(area -> {
            NetworkServiceAreaVo areaVo = new NetworkServiceAreaVo();
            BeanUtil.copyProperties(area, areaVo);
            return areaVo;
        }).toList());

        return vo;
    }

    // 批量启用或禁用服务商
    @Override
    public void updateDisableBatchById(List<Long> ids, boolean status) {
        if (CollectionUtils.isEmpty(ids)) {
            return;
        }
        networkMapper.updateDisableBatchById(ids, status);
    }

    // 根据服务商ID获取服务商名称
    @Override
    public String getNameById(Long id) {
        ZjNetwork network = this.getById(id);
        return null != network? network.getName() : "";
    }

    @Override
    public void checkJoinNetworkInviteCode(AccounLoginInfo loginInfo, String inviteCode) throws SMSException {
        NetworkInviteCodeVo inviteCodeVo = SmsVerificCodeService.checkJoinNetworkInviteCode(inviteCode, loginInfo.getPhone());
        ZjNetwork network = this.getById(inviteCodeVo.getNetworkId());
        Assert.isTrue(null != network, "邀请码错误， 请与服务商核对邀请码是否正确");
        Assert.isFalse(network.getDisabled(), "该服务商[ "+network.getName()+" ]已暂停服务，请核对此服务商是否正确");
        Assert.isTrue(network.getTeamType() == NetworkConstant.NETWORK_TEAM_TYPE_1, "当前服务商团队模式为个人，不允许增加人员，如需增加人员，请升级服务商为团队模式");
        List<ZjNetworkEmpRelation> relationList = networkEmpRelationService.getByNetworkEmpId(inviteCodeVo.getCustAccId(), loginInfo.getNetworkEmpId());
        ZjNetworkEmpRelation empRelation = null;
        if (CollectionUtil.isNotEmpty(relationList)) {
            empRelation = relationList.stream().filter(f -> Objects.equals(f.getNetworkId(), inviteCodeVo.getNetworkId())).findFirst().orElse(null);
            if (null != empRelation) {
                Assert.isFalse(empRelation.getQuit(), "当前账号已加入服务商，并且当前账号处于离职状态");
                Assert.isFalse(true, "当前账号已加入服务商");
            }
        }
    }

    // 根据邀请码获取服务商信息
    @Override
    public NetworkMobileInfoVo getNetworkInfoByInviteCode(AccounLoginInfo loginInfo, String inviteCode) throws SMSException {
        NetworkInviteCodeVo inviteCodeVo = SmsVerificCodeService.checkJoinNetworkInviteCode(inviteCode, loginInfo.getPhone());
        ZjNetwork network = this.getById(inviteCodeVo.getNetworkId());
        Assert.isTrue(null != network, "邀请码错误， 请与服务商核对邀请码是否正确");
        Assert.isFalse(network.getDisabled(), "该服务商[ "+network.getName()+" ]已暂停服务，请核对此服务商是否正确");
        Assert.isTrue(network.getTeamType() == NetworkConstant.NETWORK_TEAM_TYPE_1, "当前服务商团队模式为个人，不允许增加人员，如需增加人员，请升级服务商为团队模式");
        List<ZjNetworkEmpRelation> relationList = networkEmpRelationService.getByNetworkEmpId(inviteCodeVo.getCustAccId(), loginInfo.getNetworkEmpId());
        ZjNetworkEmpRelation empRelation = null;
        if (CollectionUtil.isNotEmpty(relationList)) {
            empRelation = relationList.stream().filter(f -> Objects.equals(f.getNetworkId(), inviteCodeVo.getNetworkId())).findFirst().orElse(null);
            if (null != empRelation) {
                Assert.isFalse(empRelation.getQuit(), "当前账号已加入服务商，并且当前账号处于离职状态");
                Assert.isFalse(true, "当前账号已加入服务商");
            }
        }
        NetworkMobileInfoVo infoVo = new NetworkMobileInfoVo();
        BeanUtil.copyProperties(network, infoVo);
        NetworkEmpRelationExtend extend = networkEmpRelationService.getManagerByNetworkId(network.getId());
        if (null != extend) {
            infoVo.setManager(extend.getManagerName());
        }
        List<ZjNetworkEmpFieldValOption> valOptionList = networkEmpFieldValOptionService.getByNetworkEmpId(loginInfo.getCustAccId(), loginInfo.getNetworkEmpId());
        infoVo.setFieldVals(networkEmpFieldValService.getByNetworkEmpId(inviteCodeVo.getCustAccId(), loginInfo.getNetworkEmpId()).stream().map(val -> {
            NetworkFieldValVo vo = new NetworkFieldValVo();
            BeanUtil.copyProperties(val, vo);
            vo.setOptVos(valOptionList.stream().filter(f -> Objects.equals(f.getNetworkEmpFieldValId(), val.getId())).map(opt -> {
                return new FieldValOptionVo(null, opt.getOptValue());
            }).toList());
            return vo;
        }).toList());
        infoVo.setAuthorFieldVals(networkEmpAuthenFieldValService.getByCustAccIdAndNetworkEmpId(loginInfo.getCustAccId(), loginInfo.getNetworkEmpId()).stream().map(valExtend -> {
            NetworkFieldValVo vo = new NetworkFieldValVo();
            BeanUtil.copyProperties(valExtend, vo);
            vo.setOptVos(valExtend.getValues().stream().map(valOpt -> {
                return new FieldValOptionVo(null, valOpt);
            }).toList());
            return vo;
        }).toList());
        return infoVo;
    }

    // 获取服务商及地址下拉数据
    @Override
    public Map<String, Object> getNetworkAddressPageSelect(Long custAccId, SelectVo selectVo) {
        PageUtil.setSelectPageLimit(selectVo);
        QueryWrapper<ZjNetwork> wrapper = new QueryWrapper<>();
        wrapper.select("id", "name", "province", "city", "area", "town", "address")
                .eq("cust_acc_id", custAccId)
                .eq("is_disabled", false);
        if (StringUtils.isNotBlank(selectVo.getName())) {
            wrapper.like("name", selectVo.getName());
        }
        Page<ZjNetwork> page = this.page(new Page<>(selectVo.getPage(), selectVo.getLimit()), wrapper);
        List<ViewNetworkEmpDetail> empDetailList = viewNetworkEmpDetailService.getManagerByNetworkIds(page.getRecords().stream().map(ZjNetwork::getId).toList());
        return PageUtil.pageList(page.getCurrent(), page.getSize(), page.getTotal(), page.getRecords().stream().map(network -> {
            SelectEmpAddressVo vo = new SelectEmpAddressVo();
            vo.setId(network.getId());
            vo.setName(network.getName());
            vo.setProvince(network.getProvince());
            vo.setCity(network.getCity());
            vo.setArea(network.getArea());
            vo.setTown(network.getTown());
            vo.setAddress(network.getAddress());
            empDetailList.stream().filter(f -> Objects.equals(f.getNetworkId(), network.getId())).findFirst().ifPresent(emp -> {
                vo.setUsername(emp.getAccountName());
                vo.setPhone(emp.getAccountPhone());
            });
            return vo;
        }).toList());
    }

    // 根据服务商ID获取服务商名称
    @Override
    public List<ZjNetwork> getNameByIds(List<Long> ids) {
        if (CollectionUtil.isEmpty(ids)) {
            return new ArrayList<>();
        }
        QueryWrapper<ZjNetwork> wrapper = new QueryWrapper<>();
        wrapper.select("id", "name")
                .in("id", ids);
        return this.list(wrapper);
    }

    // 根据服务人员ID获取对应服务商下拉数据
    @Override
    public List<SelectResultVo> getNetworkByNetworkEmpIdSelect(Long custAccId, Long networkEmpId) {
        List<ZjNetwork> networkList = networkMapper.getNetworkByNetworkEmpIdSelect(custAccId, networkEmpId);
        return networkList.stream().map(network -> {
            return new SelectResultVo(network.getId(), network.getName());
        }).toList();
    }


}
